package com.yuanqunsoft.alimigration.action;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;
import com.yuanqunsoft.alimigration.bean.ReportBean;
import com.yuanqunsoft.alimigration.bean.RuleBean;
import com.yuanqunsoft.alimigration.bean.RuleImplementBean;
import com.yuanqunsoft.alimigration.bean.RuleSetBean;
import com.yuanqunsoft.alimigration.common.JSONUtil;
import com.yuanqunsoft.alimigration.dao.support.Page;
import com.yuanqunsoft.alimigration.engine.ParseManager;
import com.yuanqunsoft.alimigration.model.Alert;
import com.yuanqunsoft.alimigration.model.Application;
import com.yuanqunsoft.alimigration.model.Module;
import com.yuanqunsoft.alimigration.model.Report;
import com.yuanqunsoft.alimigration.model.ReportWithRuleset;
import com.yuanqunsoft.alimigration.model.Rule;
import com.yuanqunsoft.alimigration.service.IAlertService;
import com.yuanqunsoft.alimigration.service.IApplicationService;
import com.yuanqunsoft.alimigration.service.IReportService;
import com.yuanqunsoft.alimigration.service.IReportWithRulesetService;
import com.yuanqunsoft.alimigration.service.IRuleImplementService;
import com.yuanqunsoft.alimigration.service.IRuleService;
import com.yuanqunsoft.alimigration.service.IRuleSetService;
import com.yuanqunsoft.alimigration.utils.FilterList;
import com.yuanqunsoft.alimigration.utils.JsonResult;

public class ReportAction extends ActionSupport {

    private static Logger logger = LogManager.getLogger(ReportAction.class);

    private JsonResult result;
    private boolean success;
    private IReportService reportService;
    private IReportWithRulesetService reportWithRulesetService;
    private IApplicationService applicationService;
    private IAlertService alertService;
    private IRuleService ruleService;
    private IRuleSetService ruleSetService;
    private IRuleImplementService ruleImplementService;
    private String repName;
    private String appName;
    private int repId;
    private List<?> datas;
    private List<?> userName;
    private String appId;
    private String errorMsg;
    private ReportBean reportBean;
    private int ruleId;

    public int getRuleId() {
        return ruleId;
    }

    public void setRuleId(int rulId) {
        this.ruleId = rulId;
    }

    public ReportBean getReportBean() {
        return reportBean;
    }

    public void setReportBean(ReportBean reportBean) {
        this.reportBean = reportBean;
    }

    public String getAppId() {
        return appId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }

    public IAlertService getAlertService() {
        return alertService;
    }

    public void setAlertService(IAlertService alertService) {
        this.alertService = alertService;
    }

    public IApplicationService getApplicationService() {
        return applicationService;
    }

    public void setApplicationService(IApplicationService applicationService) {
        this.applicationService = applicationService;
    }

    public IRuleImplementService getRuleImplementService() {
        return ruleImplementService;
    }

    public void setRuleImplementService(IRuleImplementService ruleImplementService) {
        this.ruleImplementService = ruleImplementService;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }

    public List<?> getDatas() {
        return datas;
    }

    public void setDatas(List<?> datas) {
        this.datas = datas;
    }

    public List<?> getUserName() {
        return userName;
    }

    public void setUserName(List<?> userName) {
        this.userName = userName;
    }

    public JsonResult getResult() {
        return result;
    }

    public void setResult(JsonResult result) {
        this.result = result;
    }

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public IReportService getReportService() {
        return reportService;
    }

    public void setReportService(IReportService reportService) {
        this.reportService = reportService;
    }

    public IReportWithRulesetService getReportWithRulesetService() {
        return reportWithRulesetService;
    }

    public void setReportWithRulesetService(IReportWithRulesetService reportWithRulesetService) {
        this.reportWithRulesetService = reportWithRulesetService;
    }

    public IRuleSetService getRuleSetService() {
        return ruleSetService;
    }

    public void setRuleSetService(IRuleSetService ruleSetService) {
        this.ruleSetService = ruleSetService;
    }

    public IRuleService getRuleService() {
        return ruleService;
    }

    public void setRuleService(IRuleService ruleService) {
        this.ruleService = ruleService;
    }

    public String getRepName() {
        return repName;
    }

    public void setRepName(String repName) {
        this.repName = repName;
    }

    public String getAppName() {
        return appName;
    }

    public void setAppName(String appName) {
        this.appName = appName;
    }

    public int getRepId() {
        return repId;
    }

    public void setRepId(int repId) {
        this.repId = repId;
    }

    public String Page() {
        return "page";
    }

    public String detailPage() {
        return "detail";
    }

    public String deleteReport() {
        try {
            this.getReportService().deleteReport(repId);
            this.getReportWithRulesetService().deleteByReportId(repId);
            this.setSuccess(true);
        } catch (Exception e) {
            e.printStackTrace();
            this.setSuccess(false);
        }
        return SUCCESS;
    }

    public String reportList() {
        String filter = ServletActionContext.getRequest().getParameter("filter");
        String sort = ServletActionContext.getRequest().getParameter("sort");
        String dir = ServletActionContext.getRequest().getParameter("dir");
        String orders = null;

        if (sort != null && dir != null)
            orders = sort + " " + dir;
        int startNo = Integer.parseInt(ServletActionContext.getRequest().getParameter("start"));
        int pageSize = Integer.parseInt(ServletActionContext.getRequest().getParameter("limit"));
        if (filter != null) {
            filter = FilterList.getSqlFilter(filter);
        }
        if (appId == null || appId.length() < 1) {
            Page<?> pageList = this.getReportService().pageQuery(startNo, pageSize, filter, orders);
            setResult(new JsonResult(pageList.getResult(), pageList.getTotalCount()));
        } else {
            List<?> reportList = this.getReportService().findByApplicationId(Integer.parseInt(appId));
            setResult(new JsonResult(reportList, reportList.size()));
        }
        this.setSuccess(true);
        return SUCCESS;
    }

    public String alertList() {
        try {
            List<?> alertList = this.getAlertService().findByReportId(repId);
            this.setResult(new JsonResult(alertList, alertList.size()));
            this.setSuccess(true);
        } catch (Exception e) {
            this.setSuccess(false);
        }
        return SUCCESS;
    }

    public String reportDetail() {
        try {
            ReportBean result = this.getReportService().findById(repId);
            this.setReportBean(result);
            List<ReportBean> reportList = new ArrayList<ReportBean>();
            reportList.add(result);
            this.setResult(new JsonResult(reportList, 1));
            this.setSuccess(true);
            return SUCCESS;
        } catch (Exception e) {
            this.setErrorMsg("信息读取失败！");
            this.setSuccess(false);
            return SUCCESS;
        }
    }

    // 获取某条规则所属的规则集列表
    public String ruleDetail() {
        List<RuleSetBean> ruleSets = this.getRuleSetService().findByRuleId(ruleId);
        List<String> ruleSetNames = new ArrayList<String>();
        for (RuleSetBean r : ruleSets) {
            ruleSetNames.add(r.getRusName());
        }
        this.setResult(new JsonResult(ruleSetNames, ruleSetNames.size()));
        this.setSuccess(true);
        return SUCCESS;
    }

    // 生成ParseManager初始化所需的JSON字符串
    public String generateRuleImplsJSONString(String[] ruleSetIds) {
        Set<RuleBean> rules = new HashSet<RuleBean>();
        for (String rsId : ruleSetIds) {
            List<RuleBean> ruleList = this.getRuleSetService().getRuleByRuleSetId(Integer.parseInt(rsId));
            rules.addAll(ruleList);
        }
        Set<RuleImplementBean> beans = new HashSet<RuleImplementBean>();
        for (RuleBean r : rules) {
            List<RuleImplementBean> ruleImplements = this.getRuleImplementService().getRuleImplementByRuleId(
                    r.getRulId());
            beans.addAll(ruleImplements);

        }
        String str = JSONUtil.objToStr(beans);
        logger.debug(str);
        return str;
    }

    public String generateReport() {

        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateStr = sdf.format(new Date());
        Timestamp ts = new Timestamp(System.currentTimeMillis());
        ts = Timestamp.valueOf(dateStr);

        JSONObject jsonObj = JSONObject.fromObject(datas.get(0));
        String reportName = jsonObj.get("repName").toString();
        if (this.getReportService().isNameExisted(reportName)) {
            this.setErrorMsg("报告名称已存在！");
            this.setSuccess(false);
            return SUCCESS;
        }

        String[] ruleSetIds = jsonObj.get("rulesets").toString().split(",");
        String ruleImplsJSONString = generateRuleImplsJSONString(ruleSetIds);
        // TODO : 分析生成报告
        Application application = this.getApplicationService().findByApplicationId(Integer.parseInt(appId));
        Module module = (Module) application.getModules().iterator().next();

        ParseManager manager = new ParseManager(ruleImplsJSONString);
        try {
            String resultJSONString = manager.scanWithRule(module.getModFileUrl());
            logger.debug("result is : " + resultJSONString);

            Report report = new Report();

            Set<Alert> alerts = new HashSet<Alert>();
            JSONArray array = JSONArray.fromObject(resultJSONString);
            for (int i = 0; i < array.size(); ++i) {
                JSONObject object = (JSONObject) array.get(i);
                Rule rule = ruleService.getRuleByName(object.getString("rulName"));
                JSONArray alertsArray = object.getJSONArray("alerts");
                for (int j = 0; j < alertsArray.size(); ++j) {
                    JSONObject alertJson = (JSONObject) alertsArray.get(j);
                    String aleResource = alertJson.getString("aleResource");
                    int aleLine = alertJson.getInt("aleLine");
                    alerts.add(new Alert(report, rule, module, aleResource, aleLine));
                }
            }
            report.setAlerts(alerts);
            report.setRepAlerts(alerts.size());
            report.setRepName(reportName);
            report.setApplication(application);
            report.setRepCreateTime(ts);
            // TODO 需确认是否RepFileUrl就是扫描文件的Url
            report.setRepFileUrl(module.getModFileUrl());
            this.getReportService().addReport(report);

            for (String id : ruleSetIds) {
                ReportWithRuleset instance = new ReportWithRuleset();
                instance.setRepwrId(Integer.parseInt(id));
                this.getReportWithRulesetService().addReportWithRuleset(instance);
            }
            this.setSuccess(true);
            return SUCCESS;
        } catch (Exception e) {
            e.printStackTrace();
            this.setSuccess(false);
            this.setErrorMsg("报告生成失败！");
            return SUCCESS;
        }

    }
}
